import dayjs from 'dayjs';
import { resolve } from 'node:path';
import { readPackageJSON } from 'pkg-types';
import { defineConfig, loadEnv, mergeConfig, type UserConfig } from 'vite';

import { createPlugins } from '../plugins';
import { generateModifyVars } from "../utils/modiFyVars";

import { commonConfig } from './common';

interface DefineOptions {
    overrides?: UserConfig;
    options?: {}
}

async function createDefineData(root: string) {
    try {
        const pkgJson = await readPackageJSON(root);
        const { dependencies, devDependencies, name, version } = pkgJson;

        const __APP_INFO__ = {
            pkg: {
                dependencies,
                devDependencies,
                name,
                version
            },
            lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
        };
        return {
            __APP_INFO__: JSON.stringify(__APP_INFO__);
        }
    } catch (error) {
        console.log(error);
        return {}
    }
}

export function defineApplicationConfig(DefineOptions: DefineOptions = {}) {
    const { overrides = {} } = DefineOptions;

    return defineConfig(async ({ command, mode }) => {
        const root = process.cwd();
        const isBuild = command === 'build';

        const { VITE_PUBLIC_PATH, VITE_GLOB_USE_MOCK, VITE_BUILD_COMPRESS, VITE_ENABLE_ANALYZE } = loadEnv(mode, root);

        const defineData = await createDefineData(root);
        const plugins = await createPlugins({
            isBuild,
            root,
            enableMock: VITE_GLOB_USE_MOCK === 'true',
            enableAnalyze: VITE_ENABLE_ANALYZE === 'true',
            compress: VITE_BUILD_COMPRESS
        })

        const pathResolve = (pathname: string) => resolve(root, '.', pathname)
        const timestamp = new Date().getTime();
        const applicationConfig: UserConfig = {
            base: VITE_PUBLIC_PATH,
            root: pathResolve('src'),
            resolve: {
                alias: [
                    { find: /\/@\//, replacement: pathResolve('src') + '/' },
                    { find: /\/#\//, replacement: pathResolve('types') + '/' }
                ]
            },

            build: {
                target: "es2015",
                cssTarget: "chrome80",
                rollupOptions: {
                    output: {
                        // 入口文件名
                        entryFileNames: `assets/entry/[name]-[hash]-${timestamp}.js`,
                        manualChunks: {
                            // vue: ['vue', 'pinia', 'vue-router'],
                            // antd: ['ant-design-vue'],
                            react: ['react', 'react-dom', 'react-router-dom'],
                            antd: ['antd']
                        }
                    }
                }
            },
            css: {
                preprocessorOptions: {
                    less: {
                        //additionalData 在每个文件的开头插入额外的数据。这通常用于全局导入变量或混合文件。
                        // modifyVars  用于覆盖 Less 文件中的默认变量
                        // javascriptEnabled: 启用 JavaScript 支持，允许在 Less 文件中使用 JavaScript 表达式
                        // paths: 指定解析导入路径时的查找目录 [path.resolve(__dirname, 'src')],
                        modifyVars: generateModifyVars(),
                        javascriptEnabled: true
                    }
                }
            },
            define: defineData,
            plugins
        }

        const mergedConfig = mergeConfig(commonConfig(mode), applicationConfig);

        return mergeConfig(mergedConfig, overrides);

    })
}